package com.novatec.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.novatec.beans.Cajas;
import com.novatec.beans.ContratoBean;
import com.novatec.beans.SolicitudesDevolucion;
import com.novatec.dao.mapper.CajasDetSolMapper;
import com.novatec.dao.mapper.CajasMapper;
import com.novatec.dao.mapper.ClienteMapper;
import com.novatec.dao.mapper.ContratoMapper;
import com.novatec.dao.mapper.ReposicionMapper;
import com.novatec.dao.mapper.SolicitudDevolucionMapper;
import com.novatec.dao.mapper.SolicitudesMapper;
import com.novatec.mvc.modelo.ClienteItem;
import com.novatec.mvc.modelo.Devolucion;
import com.novatec.mvc.modelo.Pedido;
import com.novatec.mvc.modelo.SolPedidoItem;
import com.novatec.mvc.modelo.Solicitud;
import com.novatec.mvc.modelo.SolicitudesItem;

public class SolicitudesDAO {

	private final Logger logger = Logger.getLogger(SolicitudesDAO.class);
	private SimpleJdbcTemplate simpleJdbcTemplate;
	private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyy");

	@Autowired
	public void init(DataSource dataSource) {
		this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void actualizarEstado(String[] nroOrden, String[] estado, String[] guia) {
		String sql = "UPDATE solicitud SET IdSolicEst = ?, guia = ? WHERE NoOrden = ?";

		for (int i = 0, total = nroOrden.length; i < total; i++) {
			if (guia[i] != null && !guia[i].equals("")) {
				simpleJdbcTemplate.update(sql, estado[i], guia[i], nroOrden[i]);
			}
		}
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void actualizarEstado(Long nroOrden, Long estado, String guia) {
		String sql = "UPDATE solicitud SET IdSolicEst = ?, guia = ? WHERE NoOrden = ?";
		simpleJdbcTemplate.update(sql, estado, guia, nroOrden);
		logger.debug("Registro actualizado");
	}
	
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void guardarSolicitudPedido(SolPedidoItem sol) {
		// TODO Auto-generated method stub

		String sql = "INSERT INTO solicitud "
				+ "(NoOrden, Transaccion, IdSolicEst, FechaReg, IdAlmacen, AlmacenCliente, IdCliente, FechaEjecucion,Guia, Reposicion) VALUES (:NoOrden, :Transaccion, :idSolicEst ,:FechaReg, :IdAlmacen, :AlmacenCliente,:IdCliente,:FechaEjecucion,:Guia,:Reposicion)";
		System.out.println(sql);

		MapSqlParameterSource mapSQL = new MapSqlParameterSource();

		mapSQL.addValue("NoOrden", sol.getNroOrden());
		mapSQL.addValue("Transaccion", sol.getTransaccion());
		mapSQL.addValue("idSolicEst", sol.getIdSolicitudEstado());
		mapSQL.addValue("FechaReg", sol.getFechaRegistro());
		mapSQL.addValue("IdAlmacen", sol.getIdAlmacen());
		mapSQL.addValue("AlmacenCliente", sol.getAlmacenCliente());
		mapSQL.addValue("IdCliente", sol.getIdCliente());
		mapSQL.addValue("FechaEjecucion", sol.getFechaEjecucion());
		mapSQL.addValue("Guia", sol.getGuia());
		if (sol.getReposicion() != null) {
			mapSQL.addValue("Reposicion", sol.getReposicion());
		} else {
			mapSQL.addValue("Reposicion", null);
		}

		simpleJdbcTemplate.update(sql, mapSQL);

		logger.debug("solicitud insertada");
		/*
		 * int count = getSimpleJdbcTemplate().update(sql, new
		 * MapSqlParameterSource().addValue("NoOrden", sol.getNroOrden())
		 * .addValue("Transaccion", sol.getTipoSolicitud())
		 * .addValue("idSolicEst", sol.getEstado()) .addValue("FechaReg",
		 * sol.getFechaEmision()) .addValue("IdAlmacen", 1010)
		 * .addValue("AlmacenCliente", "bugarin") .addValue("IdCliente", 3030));
		 */

	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void guardarSolicitudPedidoDetalle(SolPedidoItem sol) {
		// TODO Auto-generated method stub

		String sql = "INSERT INTO detsolicitud "
				+ "(IdContrato, IdTipoCaja, NoOrden, NumCajas, Responsable, DireccionEnvio, Referencia ) VALUES "
				+ "(:IdContrato, :IdTipoCaja, :NoOrden ,:NumCajas, :Responsable, :DireccionEnvio,:Referencia)";
		System.out.println(sql);

		MapSqlParameterSource mapSQL = new MapSqlParameterSource();

		mapSQL.addValue("IdContrato", sol.getIdContrato());
		mapSQL.addValue("IdTipoCaja", sol.getIdTipoCaja());
		mapSQL.addValue("NoOrden", sol.getNroOrden());
		mapSQL.addValue("NumCajas", sol.getNroCajas());
		mapSQL.addValue("Responsable", sol.getResponsable());
		mapSQL.addValue("DireccionEnvio", sol.getAlmacenCliente());
		mapSQL.addValue("Referencia", sol.getReferencia());

		simpleJdbcTemplate.update(sql, mapSQL);

		logger.debug("solicitud detalle insertada");

	}

	// dyanez
	public Map<String, Integer> getListCantidades(long idsolicitud) {
		Map<String, Integer> cantidades = new HashMap<String, Integer>();

		RowMapper<String> rm = new RowMapper<String>() {
			public String mapRow(ResultSet rs, int rowNum) throws SQLException {
				return rs.getString("t.Descripcion");
			}
		};
		List<String> tipos = simpleJdbcTemplate
				.query("SELECT t.Descripcion FROM detsolicitud d INNER JOIN tipocaja t ON d.idtipocaja = t.IdTipoCaja WHERE d.idsolicitud = ?",
						rm, idsolicitud);

		for (int i = 0; i < tipos.size(); i++) {
			String tipo = tipos.get(i);
			long cantidad = simpleJdbcTemplate
					.queryForLong(
							"SELECT d.numcajas FROM detsolicitud d INNER JOIN tipocaja t ON d.idtipocaja = t.IdTipoCaja WHERE d.idsolicitud = ? AND t.Descripcion = ?",
							idsolicitud, tipo);
			cantidades.put(tipo, (int) cantidad);
		}

		return cantidades;
	}

	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public Solicitud findSolicitud(long noorden) {
		RowMapper<Solicitud> mapper = new RowMapper<Solicitud>() {
			public Solicitud mapRow(ResultSet rs, int rowNum)
					throws SQLException {
				Solicitud item;
				String tipo = rs.getString("t.descripcion");

				if (tipo.equals("PEDIDO"))
					item = new Pedido();
				else if (tipo.equals("DEVOLUCION"))
					item = new Devolucion();
				else
					item = new Solicitud();

				item.setnContrato(rs.getLong("d.idcontrato"));
				item.setnOrden(rs.getLong("s.norden"));
				item.setFechaEmision(new Date()); // rs.getDate("s.fechaReg")
				item.setResponsable(rs.getString("s.responsable"));
				item.setDireccion(rs.getString("s.direccion"));
				item.setReferencia(rs.getString("s.referencia"));

				return item;
			}
		};

		return simpleJdbcTemplate
				.queryForObject(
						"SELECT t.descripcion, d.idcontrato, s.direccion, s.fechaReg, s.norden, s.referencia, s.responsable FROM solicitud s INNER JOIN tiposolic t ON s.idTipoSolic = t.idTipoSolic INNER JOIN detsolicitud d ON d.idsolicitud = s.idsolicitud WHERE s.norden = ?",
						mapper, noorden);
	}

	@SuppressWarnings("deprecation")
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public ContratoBean recuperarContratoXCLiente(Long idCliente,
			int tipoVigencia) {

		String sql = "SELECT IdContrato,TipoPedido,MaxAdicionalesCajas,MaxDevoluciones,Modalidad FROM contrato WHERE idcliente = :idCliente AND idcontest = " + tipoVigencia;
		SqlParameterSource name = new MapSqlParameterSource("idCliente", idCliente);
		// return simpleJdbcTemplate.query(sql, new ContratoMapper(), new
		// Object[]{idCliente,tipoVigencia} );
		
		return simpleJdbcTemplate.queryForObject(sql, new ContratoMapper(), name);
	}
	
	@SuppressWarnings("deprecation")
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public ContratoBean recuperarMaxDevolucionesMaxAdicionalesCaja(Long idCliente) {

		String sql = "SELECT IdContrato, TipoPedido, MaxAdicionalesCaja, MaxDevoluciones FROM contrato WHERE idcliente = :idCliente and modalidad = 'ROTATIVO' ";
				
		SqlParameterSource name = new MapSqlParameterSource("idCliente",
				idCliente);
		// return simpleJdbcTemplate.query(sql, new ContratoMapper(), new
		// Object[]{idCliente,tipoVigencia} );

		return simpleJdbcTemplate.queryForObject(sql, new ContratoMapper(), name);
	}

	@SuppressWarnings("deprecation")
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public ClienteItem recuperarCLienteXContrato(Long idContrato) {

		String sql = "SELECT idcliente FROM contrato WHERE idcontrato = :idContrato";
		SqlParameterSource name = new MapSqlParameterSource("idContrato", idContrato);
		// return simpleJdbcTemplate.query(sql, new ContratoMapper(), new
		// Object[]{idCliente,tipoVigencia} );

		return simpleJdbcTemplate.queryForObject(sql, new ClienteMapper(), name);
	}

	@SuppressWarnings("deprecation")
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List recuperarTiposCajas(Long idContrato) {
		String SELECT = "SELECT a.idTipoCaja, b.NombreTipoCaja, a.SaldoDisponible, a.SaldoContable, a.SaldoCliente FROM tipcajcontrat a , tipocaja b "
				+ "WHERE a.IdContrato = ? and a.idTipoCaja = b.idTipoCaja ";

		return simpleJdbcTemplate.query(SELECT, new CajasMapper(), new Object[] { idContrato });
	}

	/*
	 * select a.idTipoCaja, b.NombreTipoCaja, a.SaldoDisponible,d.NumCajas from
	 * tipCajContrat a , tipoCaja b, detsolicitud d where a.IdContrato = 2 and
	 * a.idTipoCaja = b.idTipoCaja and a.idTipoCaja = d.idTipoCaja and d.NoOrden
	 * = 20110603123818
	 */
	
	@SuppressWarnings("deprecation")
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List recuperarTiposCajasEnDetSolicitud(Long idContrato, Long nroOrden) {
		
		//String SELECT = "SELECT a.idTipoCaja, b.NombreTipoCaja, a.SaldoDisponible, d.NumCajas, d.responsable, a.SaldoCliente FROM tipcajcontrat a , tipocaja b, detsolicitud d "
		//		+ " WHERE a.IdContrato = ? and a.idTipoCaja = b.idTipoCaja and a.idTipoCaja = d.idTipoCaja and d.NoOrden = ?";

		// fvilla 09/04/2012 ini
		String SELECT = "SELECT a.idTipoCaja, b.NombreTipoCaja, a.SaldoDisponible, d.NumCajas, d.responsable, a.SaldoCliente,d.DireccionEnvio,d.Referencia FROM tipcajcontrat a , tipocaja b, detsolicitud d "
			+ " WHERE a.IdContrato = ? and a.idTipoCaja = b.idTipoCaja and a.idTipoCaja = d.idTipoCaja and d.NoOrden = ?";
		// fvilla 09/04/2012 fin
		
		return simpleJdbcTemplate.query(SELECT, new CajasDetSolMapper(),
				new Object[] { idContrato, nroOrden });
	}
	
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public Integer recuperarNumCajasByNroOrden(Long nroOrden) {
		String SELECT = "SELECT numCajas FROM detsolicitud WHERE noorden = ?";
		
		return simpleJdbcTemplate.queryForInt(SELECT, nroOrden);
	}
	
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public Long recuperarIdEstadoSolicitudByNroOrden(Long nroOrden) {
		String SELECT = "SELECT idSolicEst FROM solicitud WHERE noorden = ?";
		
		return simpleJdbcTemplate.queryForLong(SELECT, nroOrden);
	}

	//select guia from solicitud where NoOrden =
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public SolicitudesItem recuperarGuiaByNroOrden(Long nroOrden) {
		String SELECT = "SELECT guia FROM solicitud WHERE noorden = :noorden";
		SqlParameterSource name = new MapSqlParameterSource("noorden", nroOrden);
		
		return simpleJdbcTemplate.queryForObject(SELECT, new SolicitudesMapper(),name);
	}

	public Cajas recuperarReposicionEnSolicitud(Long noOrden, Long idCliente) {

		String sql = "SELECT Reposicion FROM solicitud WHERE NoOrden = :orden and IdCliente= " + idCliente;
		SqlParameterSource name = new MapSqlParameterSource("orden", noOrden);
		// return simpleJdbcTemplate.query(sql, new ContratoMapper(), new
		// Object[]{idCliente,tipoVigencia} );

		return simpleJdbcTemplate.queryForObject(sql, new ReposicionMapper(), name);
	}
	
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void actualizarSaldoDisponible(Long idContrato, Long idTipoCaja, Integer saldoDisponible) {
		// TODO Auto-generated method stub
		
		String sql = "UPDATE tipcajcontrat SET SaldoDisponible = :saldoDisponible WHERE IdContrato =:idContrato and idTipoCaja =:idTipoCaja";
		
		MapSqlParameterSource mapSQL= new MapSqlParameterSource();
		
		mapSQL.addValue("saldoDisponible",saldoDisponible );
		mapSQL.addValue("idContrato",idContrato );
		mapSQL.addValue("idTipoCaja",idTipoCaja );
		
		simpleJdbcTemplate.update(sql, mapSQL);
	
		logger.debug("saldo disponible pedido actualizado.");
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void actualizarSaldoPorDevolver(Long idContrato, Long idTipoCaja, Integer saldoDevolver) {
		// TODO Auto-generated method stub
		
		String sql = "UPDATE tipcajcontrat SET SaldoPorDevolver = :saldoDevolver WHERE IdContrato =:idContrato and idTipoCaja =:idTipoCaja" ;
		
		MapSqlParameterSource mapSQL= new MapSqlParameterSource();
		
		mapSQL.addValue("saldoDevolver",saldoDevolver );
		mapSQL.addValue("idContrato",idContrato );
		mapSQL.addValue("idTipoCaja",idTipoCaja );
		
		simpleJdbcTemplate.update(sql, mapSQL);
	
		logger.debug("saldo por devolver pedido actualizado.");
		
		
	}
	
	@SuppressWarnings("deprecation")
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public SolicitudesDevolucion recuperarTotalDevolucionesPorCliente(Long idCliente) {

		String sql = "SELECT count(NoOrden) FROM solicitud WHERE Transaccion='devolucion' and idCliente = :id and MONTH(CURDATE())";
			SqlParameterSource name = new MapSqlParameterSource("id", idCliente);
		// return simpleJdbcTemplate.query(sql, new ContratoMapper(), new
		// Object[]{idCliente,tipoVigencia} );

		return simpleJdbcTemplate.queryForObject(sql, new SolicitudDevolucionMapper(), name);
	}

}
